home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_08_10
/
8n10055a
< prev
next >
Wrap
Text File
|
1990-11-05
|
23KB
|
877 lines
//////////////////////////////////////////////////////////////////////////
// //
// ANTHILL //
// by //
// Mark Weaver and Alex Lane //
// //
//////////////////////////////////////////////////////////////////////////
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <dos.h>
#include <ctype.h>
#include <string.h>
#include "anthill.h"
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
//////////////////////////////////////////////////////////////////////////
// //
// Global Variables //
// //
//////////////////////////////////////////////////////////////////////////
float gfCellSizeX; // Width (in pixels) of a cell
float gfCellSizeY; // Height (in pixels) of a cell
unsigned guFoodUnits[100][100]; // How many units of food in each cell
int gnTimeToHatch; // Cycles required to become a worker ant
int gnDropDistance; // Distance at which to drop food for queen
unsigned long gulTotalFood; // Total units of food on board
unsigned guWorkers; // Total workers on board
unsigned guEggs; // Total number of eggs on board
unsigned long gulCycle; // Which life cycle are we in?
unsigned guWorkersPortion; // What a worker eats from each food packet
unsigned guMaxLifeSpan; // Longest life span
unsigned guBirthRate; // Percentage of cycles queen lays an egg
unsigned guMaxSpeed; // Maximum speed for worker ants
unsigned guQueensEnergy; // Queens extra starting energy level
unsigned guInitEggs; // Initial # of eggs
unsigned guInitWorkers; // Initial # of worker ants
unsigned guInitFood; // Initial # of cells with food
unsigned guPause; // Milliseconds to pause each cycle
Queen *gQueen; // Queen ant
Worker *headOfAntList; // Head of linked list of worker ants
//////////////////////////////////////////////////////////////////////////
// //
// MOVER class functions //
// //
//////////////////////////////////////////////////////////////////////////
Mover::Mover(unsigned uMaxRng, unsigned uMaxSpd, int nStartX, int nStartY)
{
uMaxRange = uMaxRng;
uMaxSpeed = uMaxSpd;
nX = nInitX = nStartX;
nY = nInitY = nStartY;
bVisible = FALSE;
nVelX = -uMaxSpeed + random(uMaxSpeed + 1);
nVelY = -uMaxSpeed + random(uMaxSpeed + 1);
}
int Mover::getX( void )
{
return nX;
}
int Mover::getY( void )
{
return nY;
}
BOOLEAN Mover::moveTo(int nNewX, int nNewY )
{
if ((distance(nNewX, nNewY, nInitX, nInitY) <= uMaxRange || !uMaxRange)){
erase();
if ((nX = nNewX) < 0){
nX = 0;
}
else
if (nX > 99) {
nX = 99;
}
if ((nY = nNewY) < 0){
nY = 0;
}
else
if (nY > 99) {
nY = 99;
}
draw();
return( TRUE );
}
else {
return( FALSE );
}
}
BOOLEAN Mover::move( void )
{
int nNewX, nNewY;
nNewX = nX + nVelX;
nNewY = nY + nVelY;
if ((distance(nNewX, nNewY, nInitX, nInitY) <= uMaxRange || !uMaxRange)){
erase();
if ((nX = nNewX) < 0) {
nX = 0;
nVelX = -nVelX;
}
else
if (nX > 99) {
nX = 99;
nVelX = -nVelX;
}
if ((nY = nNewY) < 0) {
nY = 0;
nVelY = -nVelY;
}
else
if (nY > 99) {
nY = 99;
nVelY = -nVelY;
}
draw();
// Turn once in a while
if (random(100) < 10){
nVelX += random(3) - 1;
nVelY += random(3) - 1;
if (nVelX > uMaxSpeed) {
nVelX = uMaxSpeed;
}
else
if (nVelX < -uMaxSpeed) {
nVelX = -uMaxSpeed;
}
if (nVelY > uMaxSpeed) {
nVelY = uMaxSpeed;
}
else
if (nVelY < -uMaxSpeed) {
nVelY = -uMaxSpeed;
}
// Make sure I do not stop
if (nVelX == 0 && nVelY == 0) {
nVelX = 1+random(uMaxSpeed-1);
nVelY = -1-random(uMaxSpeed-1);
}
}
return( TRUE );
}
else {
draw();
return( FALSE );
}
}
void Mover::show( void )
{
if (!bVisible){
draw();
bVisible = TRUE;
}
}
void Mover::erase( void )
{
moverDrawFunc(nX, nY, FALSE, BACKGROUND );
}
void Mover::draw( void )
{
moverDrawFunc(nX, nY, TRUE, color);
}
void Mover::moverDrawFunc(int nX, int nY, BOOLEAN bVisible, int nColor)
{
setfillstyle(SOLID_FILL, bVisible ? nColor : BACKGROUND);
bar(nX * gfCellSizeX, nY * gfCellSizeY,
(nX + 0.5) * gfCellSizeX, (nY + 1) * gfCellSizeY - 1);
}
//////////////////////////////////////////////////////////////////////////
// //
// ANT class functions //
// //
//////////////////////////////////////////////////////////////////////////
Ant::Ant( int Range, int Speed, int nX, int nY, int Energy) :
Consumer( Energy ), // constructor
Mover( Range, Speed, nX, nY ) // constructor
{
bDead= FALSE;
}
// Dying ant updates counters and drops any food he is carying
void Ant::die(void)
{
bDead = TRUE;
nEnergy = 0;
erase();
}
void Ant::doTheAntThing(void)
{
// Age the ant
nAge++;
// Every ant uses one energy unit per cycle
nEnergy -= 1;
if (nEnergy<1 || nAge > nLifeSpan) {
die();
}
else {
if (bEgg) {
// force redraw in case egg has been walked on
moveTo(nX, nY);
if (nAge > gnTimeToHatch) {
bEgg = FALSE;
color = GREEN;
guEggs--;
guWorkers++;
}
}
}
}
//////////////////////////////////////////////////////////////////////////
// //
// QUEEN class functions //
// //
//////////////////////////////////////////////////////////////////////////
Queen::Queen( unsigned InitEnergy, int QRange, int QSpeed,
int QIntitX, int QInitY, unsigned _birthRate ) :
Ant(QRange, QSpeed, QIntitX, QInitY, random(100)+InitEnergy )
{
birthRate = _birthRate;
color = YELLOW;
}
// Queen ant lays eggs once in a while
void Queen::layEgg(void)
{
new Worker(TRUE, nX, nY);
guEggs++;
nEnergy -= MIN(150, nEnergy);
}
void Queen::doTheAntThing(void)
{
// Every ant uses one energy unit per cycle
nEnergy -= 1;
nVelX = random(uMaxSpeed+1)*(random(2) ? 1 : -1 );
nVelY = random(uMaxSpeed+1)*(random(2) ? 1 : -1 );
if (nEnergy<1) {
die();
}
else {
// Turn around if at limits of area!
if (distance(nInitX, nInitY, nX + nVelX, nY + nVelY) > uMaxRange) {
nVelX = -nVelX ;
nVelY = -nVelY ;
}
// Move somewhere
move();
if (guFoodUnits[nX][nY]) {
eatFood(guFoodUnits[nX][nY]);
}
// need a minimum of 750 units to be able to lay an egg
// (the idea here is to conserve energy)
if ((nEnergy > 750) && (random(100) < birthRate)) {
layEgg();
}
// if the energy level gets too high, improve the chances of
// laying an egg; and vice versa
// keep the birthrate between 50 and 5 percent.
if ((nEnergy > 5000) && (birthRate < 49)) birthRate++;
if ((nEnergy < 3000) && (birthRate > 6)) birthRate--;
}
}
//////////////////////////////////////////////////////////////////////////
// //
// WORKER c